package com.buli.blmall.admin.common.service;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.buli.blmall.admin.client.PushClient;
import com.buli.blmall.admin.common.request.SmsSend;
import com.buli.blmall.admin.common.response.Result;
import com.buli.blmall.admin.consts.CacheKey;
import com.buli.blmall.admin.consts.ConfigKey;
import com.buli.blmall.admin.consts.Constants;
import com.buli.blmall.admin.exception.SmsException;
import com.buli.blmall.admin.exception.error.SmsErrorCode;
import com.buli.blmall.admin.system.service.SysConfigService;
import com.buli.blmall.admin.core.cache.RedisClient;
import com.buli.blmall.admin.utils.HttpUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author xiang.gao
 * @date 2025/2/20 17:52
 */
@Slf4j
@Service
@AllArgsConstructor
public class SmsService {

    private final SysConfigService sysConfigService;
    private final CaptchaService captchaService;
    private final RedisClient redisClient;

    /**
     * 发送短信验证码
     * @param smsSend
     */
    public void sendCaptcha(SmsSend smsSend) {
        //两次发送间隔时间
        String codeKey = CacheKey.SMS_CODE_KEY.concat(smsSend.getPhoneNumber());
        JSONObject jsonObject = redisClient.getValue(codeKey);
        if (jsonObject != null) {
            Long sendTime = jsonObject.getLong("sendTime");
            if (DateUtil.current() - sendTime < Constants.SMS_SEND_INTERVAL) {
                throw new SmsException(SmsErrorCode.SMS_SEND);
            }
        }
        //每日发送次数限制
        String timesKey = CacheKey.SMS_TIMES_KEY.concat(smsSend.getPhoneNumber());
        int sendTimes = redisClient.getValue(timesKey);
        String configTimes = sysConfigService.selectConfigByKey(ConfigKey.SMS_SEND_TIMES);
        if (sendTimes >= Integer.parseInt(configTimes)) {
            throw new SmsException(SmsErrorCode.SMS_MAX_LIMIT);
        }

        //如果开启验证码
        String captchaEnabled = sysConfigService.selectConfigByKey(ConfigKey.SYSTEM_CONFIG_KEY_CAPTCHA);
        if (BooleanUtil.toBoolean(captchaEnabled)) {
            captchaService.verify(smsSend.getCaptchaId(), smsSend.getCaptchaCode());
        }
        //生成随机验证码
        String smsCode = RandomUtil.randomNumbers(6);
        log.info("发送验证码,key={},code={}", codeKey, smsCode);

        //调用发短信接口
        Result<?> result = PushClient.sendCaptcha(smsCode, Constants.CAPTCHA_EXPIRATION, smsSend.getPhoneNumber());
        if (!result.isSuccess()) {
            throw new SmsException(SmsErrorCode.SMS_SEND_FAIL);
        }

        //保存短信验证码
        jsonObject = JSONUtil.createObj().putOnce("code", smsCode).putOnce("sendTime", DateUtil.current());
        redisClient.setValue(codeKey, jsonObject, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

        //记录当天方式次数
        long timesExpired = DateUtil.between(new Date(), DateUtil.endOfDay(new Date()), DateUnit.SECOND);
        redisClient.setValue(timesKey, sendTimes + 1, timesExpired, TimeUnit.SECONDS);

    }

    /**
     * 校验短信验证码
     */
    public boolean verify(String phoneNumber, String smsCode) {
        String codeKey = CacheKey.SMS_CODE_KEY.concat(phoneNumber);
        JSONObject jsonObject = redisClient.getValue(codeKey);
        if (jsonObject == null) {
            return false;
        }
        String code = jsonObject.getStr("code");
        boolean verify = StringUtils.equals(code, smsCode);
        if (verify) {
            redisClient.deleteValue(codeKey);
        }
        return verify;
    }

}
